package com.ecoolex.discount.sales.core.manager;

import com.ecoolex.discount.sales.Constant;
import com.ecoolex.discount.sales.core.dao.DiscountOrderDAO;
import com.ecoolex.discount.sales.core.external.DaZhongOrderPushExternalService;
import com.ecoolex.discount.sales.core.service.NihaoPayService;
import com.ecoolex.discount.sales.core.service.WeiXinPayService;
import com.ecoolex.discount.sales.core.service.YouWorldService;
import com.ecoolex.discount.sales.entity.*;
import com.ecoolex.discount.sales.entity.DiscountOrder.Column;
import com.ecoolex.discount.sales.entity.DiscountOrderExample.Criteria;
import com.ecoolex.discount.sales.enums.*;
import com.ecoolex.discount.sales.pojo.CreateOrderChannelDTO;
import com.ecoolex.discount.sales.pojo.QueryDiscountOrderDTO;
import com.ecoolex.discount.sales.pojo.QueryUserDiscountOrderDTO;
import com.ecoolex.framework.common.enums.ResultCode;
import com.ecoolex.framework.common.exception.BizException;
import com.ecoolex.framework.common.pojo.Page;
import com.ecoolex.framework.common.pojo.Pagination;
import com.ecoolex.framework.common.pojo.Sorting;
import com.ecoolex.framework.common.pojo.Sortings;
import com.ecoolex.framework.common.util.BizAssert;
import com.ecoolex.framework.common.util.Check;
import com.ecoolex.framework.common.util.RandomUtil;
import com.ecoolex.framework.modularize.api.auth.user.ConsumerMember;
import com.ecoolex.framework.modularize.api.auth.user.ConsumerMemberLoginRecord;
import com.ecoolex.framework.modularize.api.auth.user.ConsumerMemberManager;
import com.ecoolex.framework.modularize.api.service.config.SystemConfig;
import com.ecoolex.user.system.enums.UserLoginSource;
import com.google.common.collect.Lists;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.List;

import static com.ecoolex.discount.sales.entity.DiscountOrder.IS_DELETED;
import static com.ecoolex.discount.sales.entity.DiscountOrder.NOT_DELETED;

@Service
public class DiscountOrderManager {
	
	private static final Logger log = LoggerFactory.getLogger(DiscountOrderManager.class);
	
    @Autowired
    private DiscountOrderDAO dao;

    @Autowired
    private DiscountBrandManager discountBrandManager;
    @Autowired
    private DiscountProductManager discountProductManager;
    @Autowired
    private DiscountProductGiftCardManager discountProductGiftCardManager;
    @Autowired
    private DiscountProductVouchersManager discountProductVouchersManager;
    @Autowired
    private DiscountOrderOperationRecordManager discountOrderOperationRecordManager;
    @Autowired
    private CardVoucherPackageManager cardVoucherPackageManager;
    @Autowired
    private DiscountOrderDetailManager discountOrderDetailManager;
    
    @Autowired
    private DiscountOrderOutinfoManager outinfoManager;
    
    @Autowired
    private DaZhongOrderPushExternalService daZhongOrderPushExternalService;
    
    @Autowired
    private ConsumerMemberManager consumerMemberManager;
    
    @Autowired
    private YouWorldService youWorldService;
    
    @Autowired
    private YouWorldUserManager youWorldUserManager;
    
    @Autowired
    private SystemConfig systemConfig;
    
    @Autowired
    private DiscountOrderRefundManager discountOrderRefundManager;
    
    @Autowired
    private NihaoPayService nihaoPayService;

    /**
     * 通用验证
     */
    private void verify(DiscountProductWithBLOBs product, DiscountProductDiscountMode discountMode) {
        BizAssert.isTrue(Check.notNull(product), ResultCode.VERIFY.build(10), "产品不存在");
        BizAssert.isTrue(DiscountProductStatus.ONLINE.equal(product.getStatus()), ResultCode.VERIFY.build(11), "产品已下线");
        BizAssert.isTrue(DiscountProductAvailableStatus.ENABLE.equal(product.getAvailableStatus()), ResultCode.VERIFY.build(12), "产品库存不足");
        BizAssert.isTrue(discountMode.equal(product.getDiscountMode()), ResultCode.VERIFY.build(13), "此下单接口不支持该类型产品");
        if(DiscountProductServiceType.YOU_WORLD.equal(product.getServiceType()) && Check.notNullOrEmpty(product.getServiceDataId())) {
        	//实时校验由我礼品卡是否可用
        	Boolean cardStatus = youWorldService.checkCardStatus(Integer.valueOf(product.getServiceDataId()));
        	BizAssert.isTrue(cardStatus,ResultCode.VERIFY.build(14), "产品补货中");
        }
    }

    private void verify(DiscountProductWithBLOBs product,Integer userId,BigDecimal faceValue) {
    	if(DiscountProductServiceType.YOU_WORLD.equal(product.getServiceType())) {
        	//校验由我新用户每日限额
        	ConsumerMember consumerMember = consumerMemberManager.getByUserId(userId);
        	if(Check.notNull(consumerMember.getPhone())) {
        		//是否是由我会员
        		YouWorldUser youWorldUser = youWorldUserManager.getByPhone(consumerMember.getPhone());
        		//不是会员检验限额
        		if(Check.isNull(youWorldUser)) {
        			String limit = systemConfig.get(Constant.CONFIG_YOU_WORLD_BUY_LIMIT);
        			if(Check.notNull(limit)) {
        				BigDecimal value = BigDecimal.valueOf(Long.valueOf(limit));
        				//查询当日用户累计订单金额
        				BigDecimal todayAmount = dao.sumPriceByDate(new SimpleDateFormat("yyyy-MM-dd").format(new Date()), userId);
        				if(Check.notNull(todayAmount)) {
        					BizAssert.isTrue(Check.isLessThanEqual(faceValue.add(todayAmount), value),ResultCode.BIZ.build(10), "您已超出当日限额，目前剩余额度：{}美元",value.subtract(todayAmount).setScale(2, RoundingMode.HALF_UP));
        				}else {
        					BizAssert.isTrue(Check.isLessThanEqual(faceValue, value),ResultCode.BIZ.build(11), "您已超出当日限额，目前剩余额度：{}美元",value);
        				}
        			}
        		}
        	}
    	}
    }
    
    private void verify(DiscountBrandWithBLOBs brand) {
        BizAssert.isTrue(Check.notNull(brand), ResultCode.VERIFY.build(14), "品牌不存在");
        BizAssert.isTrue(DiscountBrandStatus.ONLINE.equal(brand.getStatus()), ResultCode.VERIFY.build(15), "品牌已下线");
    }

    /**
     * 礼品卡验证
     */
    private void verify(DiscountProductGiftCard giftCardProduct) {
        // 固定面额
        BizAssert.isTrue(Check.notNull(giftCardProduct), ResultCode.VERIFY.build(30), "礼品卡产品不存在");
        BizAssert.isTrue(DiscountProductGiftCardCounterPriceType.FIXED.equal(giftCardProduct.getCounterPriceType()),
                ResultCode.VERIFY.build(31),
                "礼品卡产品只支持固定面额方式下单");
    }

    /**
     * 礼品卡动态面额验证
     *
     * @param giftCardProduct
     * @param faceValue
     */
    private void verify(DiscountProductGiftCard giftCardProduct, BigDecimal faceValue) {
        // 固定面额
        BizAssert.isTrue(Check.notNull(giftCardProduct), ResultCode.VERIFY.build(30), "礼品卡产品不存在");
        BizAssert.isTrue(DiscountProductGiftCardCounterPriceType.VARIABLE.equal(giftCardProduct.getCounterPriceType()),
                ResultCode.VERIFY.build(31),
                "礼品卡产品只支持动态面额方式下单");
        BizAssert.isTrue(Check.notNull(faceValue), ResultCode.VERIFY.build(32), "礼品卡面额不能为空");
        BizAssert.isTrue(Check.isRangeWithin(faceValue, giftCardProduct.getMinCounterPrice(), giftCardProduct.getMaxCounterPrice()),
                ResultCode.VERIFY.build(33),
                "礼品卡面额只支持{}-{}", giftCardProduct.getMinCounterPrice(), giftCardProduct.getMaxCounterPrice());
        BizAssert.isTrue(faceValue.scale() <= 2, ResultCode.VERIFY.build(34), "礼品卡面额只支持2位小数");
    }

    /**
     * 折扣券验证
     */
    private void verify(DiscountProductVouchers vouchers, Integer buyNumber) {
        BizAssert.isTrue(Check.notNull(vouchers), ResultCode.VERIFY.build(30), "折扣券产品不存在");
        BizAssert.isTrue(Check.notNullAndGtZero(buyNumber), ResultCode.VERIFY.build(31), "购买数量不能为并且大于零");
        BizAssert.isTrue(buyNumber <= vouchers.getMaxBuyNumber(), ResultCode.VERIFY.build(31), "超过最大购买数量");
    }

    /**
     * 冻结库存
     *
     * @param order
     * @param updateUser
     */
    private void freeze(DiscountOrder order, String updateUser) {
        boolean flag = true;
        if (DiscountProductDiscountMode.GIFT_CARD.equal(order.getDiscountMode())) {
            flag = discountProductGiftCardManager.freeze(order, updateUser);
        } else if (DiscountProductDiscountMode.VOUCHERS.equal(order.getDiscountMode())) {
            flag = discountProductVouchersManager.freeze(order, updateUser);
//        } else if (DiscountProductDiscountMode.RECHARGE.equal(record.getDiscountMode())) {
//            discountProductRechargeManager.validityVerify(record);
        }
        BizAssert.isTrue(flag, ResultCode.VERIFY.build(12), "产品库存不足, 冻结失败");
    }

    /**
     * 解冻库存
     *
     * @param order
     * @param updateUser
     */
    private void unfreeze(DiscountOrder order, String updateUser) {
        if (DiscountProductDiscountMode.GIFT_CARD.equal(order.getDiscountMode())) {
            discountProductGiftCardManager.unfreeze(order, updateUser);
        } else if (DiscountProductDiscountMode.VOUCHERS.equal(order.getDiscountMode())) {
            discountProductVouchersManager.unfreeze(order, updateUser);
//        } else if (DiscountProductDiscountMode.RECHARGE.equal(record.getDiscountMode())) {
//            discountProductRechargeManager.validityVerify(record);
        }
    }

    /**
     * 礼品卡
     */
    @Transactional
    public DiscountOrder createQuotaGiftCardOrder(Integer userId, Integer productId,CreateOrderChannelDTO channel, String createUser) {
        return createGiftCardOrder(true, userId, productId, null,channel, createUser);
    }

    @Transactional
    public DiscountOrder createGiftCardOrder(Integer userId, Integer productId, BigDecimal faceValue,CreateOrderChannelDTO channel, String createUser) {
        return createGiftCardOrder(false, userId, productId, faceValue,channel, createUser);
    }

    private DiscountOrder createGiftCardOrder(boolean isQuota, Integer userId, Integer productId, BigDecimal faceValue,CreateOrderChannelDTO channel, String createUser) {
        // 产品
        DiscountProductWithBLOBs product = discountProductManager.getById(productId);
        verify(product, DiscountProductDiscountMode.GIFT_CARD);
        // 品牌
        DiscountBrandWithBLOBs brand = discountBrandManager.getDiscountBrand(product.getBrandId());
        verify(brand);
        // 礼品卡
        DiscountProductGiftCard giftCardProduct = discountProductGiftCardManager.getByProductId(productId);
        if (isQuota) {
            verify(giftCardProduct);
        } else {
            verify(giftCardProduct, faceValue);
        }

        // 创建订单
        DiscountOrder order = create(userId, brand, product, createUser);
        // 生成价格
        order.setBuyNumber(1);
        order.setCurrencyType(giftCardProduct.getCurrencyType());
        if (isQuota) {
            order.setBuyCounterPrice(giftCardProduct.getCounterPrice());
            order.setRetailPrice(giftCardProduct.getRetailPrice());
        } else {
        	BigDecimal discountPercent = giftCardProduct.getCounterPriceDiscountPercent();
            order.setBuyCounterPrice(faceValue);
            order.setRetailPrice(faceValue.subtract(faceValue.multiply(discountPercent.divide(BigDecimal.valueOf(100)))));
        }
        order.setBuyTotalCounterPrice(order.getBuyCounterPrice().multiply(BigDecimal.valueOf(order.getBuyNumber())));
        order.setTotalRetailPrice(order.getRetailPrice().multiply(BigDecimal.valueOf(order.getBuyNumber())));
        order.setTotalPrice(order.getTotalRetailPrice());
        order.setDiscountPrice(order.getBuyTotalCounterPrice().subtract(order.getTotalRetailPrice()));
        //由我礼品卡限额验证
        verify(product,userId,order.getTotalRetailPrice());
        // 判断支付最小金额
        BizAssert.isTrue(Check.isGreatThanEqual(order.getTotalPrice(), new BigDecimal("0.01")),
                ResultCode.VERIFY.build(40),
                "支付金额小于0.01无法创建订单");
        // 冻结库存
        freeze(order, createUser);

        dao.insert(order);
        //保存渠道信息
        saveOrderChannel(order.getOrderId(),userId,channel,createUser);
        return order;
    }

    /**
     * 折扣券
     */
    @Transactional
    public DiscountOrder createVouchersOrder(Integer userId, Integer productId, Integer buyNumber,CreateOrderChannelDTO channel, String createUser) {
        // 产品
        DiscountProductWithBLOBs product = discountProductManager.getById(productId);
        verify(product, DiscountProductDiscountMode.VOUCHERS);
        // 品牌
        DiscountBrandWithBLOBs brand = discountBrandManager.getDiscountBrand(product.getBrandId());
        verify(brand);
        // 折扣券
        DiscountProductVouchers vouchers = discountProductVouchersManager.getByProductId(productId);
        verify(vouchers, buyNumber);
        // 创建订单
        DiscountOrder order = create(userId, brand, product, createUser);
        // 生成价格
        order.setBuyNumber(buyNumber);
        order.setCurrencyType(vouchers.getCurrencyType());
        order.setBuyCounterPrice(vouchers.getCounterPrice());
        order.setRetailPrice(vouchers.getRetailPrice());
        order.setBuyTotalCounterPrice(order.getBuyCounterPrice().multiply(BigDecimal.valueOf(order.getBuyNumber())));
        order.setTotalRetailPrice(order.getRetailPrice().multiply(BigDecimal.valueOf(order.getBuyNumber())));
        order.setTotalPrice(order.getTotalRetailPrice());
        // 判断支付最小金额
        BizAssert.isTrue(Check.isGreatThanEqual(order.getTotalPrice(), new BigDecimal("0.01")),
                ResultCode.VERIFY.build(40),
                "支付金额小于0.01无法创建订单");
        // 冻结库存
        freeze(order, createUser);

        dao.insert(order);
        //保存渠道信息
        saveOrderChannel(order.getOrderId(),userId,channel,createUser);
        return order;
    }
    
    /**
     * 存储渠道信息
     * @param orderId
     * @param userId
     * @param channel
     * @param createUser
     */
    private void saveOrderChannel(Integer orderId,Integer userId,CreateOrderChannelDTO channel, String createUser) {
        if(Check.notNull(channel)) {
        	outinfoManager.add(orderId, channel, createUser);
        }else {
        	//查询最近的登录信息
            ConsumerMemberLoginRecord loginRecord = consumerMemberManager.getLoginRecordByUserId(userId);
            //来源第三方登录
            if(loginRecord.getSource().equals(UserLoginSource.THIRD_PARTY_API.real())) {
            	//银联云闪付渠道
            	if(loginRecord.getSourceValue().equals("UnionPay")) {
            		CreateOrderChannelDTO channelDTO = new CreateOrderChannelDTO();
            		channelDTO.setChannelId(DiscountOrderChannel.UNIONPAY.real());
            		//TODO 云闪付渠道号？、前端下礼品卡订单时去掉渠道参数
            		channelDTO.setOutId("unionpay");
            		outinfoManager.add(orderId, channelDTO, createUser);
            	}
            }
        }
    }

    /**
     * TODO 充值
     */
    @Transactional
    public DiscountOrder createQuotaRechargeOrder(Integer userId, Integer productId, Integer buyNumber, String account, String createUser) {
        // TODO
        return null;
    }

    @Transactional
    public DiscountOrder createRechargeOrder(Integer userId, Integer productId, BigDecimal faceValue, String account, String createUser) {
        return null;
    }
    
    private DiscountOrder create(Integer userId, DiscountBrandWithBLOBs brand, DiscountProductWithBLOBs product, String createUser) {
    	ConsumerMember consumerMember = consumerMemberManager.getByUserId(userId);
    	DiscountOrder order = new DiscountOrder();
        order.setOrderNo(RandomUtil.randomInt(24));
        order.setUserId(userId);
        order.setMobileNumber("+"+consumerMember.getPhoneCountryCode()+" "+consumerMember.getPhone());
        order.setRegionType(product.getRegionType());
        order.setBrandId(product.getBrandId());
        order.setProductId(product.getProductId());
        order.setDiscountMode(product.getDiscountMode());
        order.setServiceType(product.getServiceType());
        order.setServiceDataId(product.getServiceDataId());
        order.setOrderStatus(DiscountOrderStatus.CREATE.real());
        order.setCancelStatus(DiscountOrderCancelStatus.UNKNOWN.real());
        order.setProcessStatus(DiscountOrderProcessStatus.UNKNOWN.real());
        order.setRefundStatus(DiscountOrderRefundStatus.UNKNOWN.real());
        order.setCompleteStatus(DiscountOrderCompleteStatus.UNKNOWN.real());
        order.setDeleted(NOT_DELETED);
        order.setCreateUser(createUser);
        order.setCreateTime(Date.from(Instant.now()));
        order.setUpdateUser(createUser);
        order.setUpdateTime(Date.from(Instant.now()));

        // 生成质保期
        if (DiscountProductShelfLifeStrategy.FIXED.equal(product.getShelfLifeStrategy())) {
            order.setShelfLife(product.getFixedEndShelfLife());
        } else if (DiscountProductShelfLifeStrategy.DYNAMIC.equal(product.getShelfLifeStrategy())) {
            DiscountProductDynamicShelfLifeType type = DiscountProductDynamicShelfLifeType.realValueOf(product.getDynamicShelfLifeType());
            if (type == DiscountProductDynamicShelfLifeType.YEAR) {
                order.setShelfLife(Date.from(Instant.now().plus(product.getDynamicShelfLifeValue()*365, ChronoUnit.DAYS)));
            } else if (type == DiscountProductDynamicShelfLifeType.MONTH) {
                order.setShelfLife(Date.from(Instant.now().plus(product.getDynamicShelfLifeValue()*30, ChronoUnit.DAYS)));
            } else if (type == DiscountProductDynamicShelfLifeType.DAY) {
                order.setShelfLife(Date.from(Instant.now().plus(product.getDynamicShelfLifeValue(), ChronoUnit.DAYS)));
            } else if (type == DiscountProductDynamicShelfLifeType.HOURS) {
                order.setShelfLife(Date.from(Instant.now().plus(product.getDynamicShelfLifeValue(), ChronoUnit.HOURS)));
            }
        }
        return order;
    }

    /**
     * 支付通知
     */
    void payedNotify(PaymentOrder order, String updateUser) {
        // 不是支付成功状态不更新
        if (PaymentOrderStatus.PAY_SUCCEED.notEqual(order.getStatus())) {
            return;
        }
        // 获取订单数据, 就算删除也不管. 先更新订单状态
        DiscountOrder record = new DiscountOrder();
        if (WeiXinPayService.PAYMENT_TYPE.equalsIgnoreCase(order.getPaymentType())) {
            record.setPaymentChannel(DiscountOrderPaymentChannel.WEI_XIN.real());
        }else if(NihaoPayService.PAYMENT_TYPE.equalsIgnoreCase(order.getPaymentType())) {
        	record.setPaymentChannel(DiscountOrderPaymentChannel.NIHAO_PAY.real());
        }
        record.setPaymentNo(order.getPaymentNo());
        record.setPaymentTime(order.getPaymentTime());
        if ("CNY".equalsIgnoreCase(order.getPaymentCurrencyType())) {
            record.setPaymentRMBAmount(order.getPaymentPrice());
        }else {
        	record.setPaymentRMBAmount(order.getRmbAmount());
        }
        record.setOrderStatus(DiscountOrderStatus.PAID.real());
        record.setUpdateUser(updateUser);
        record.setUpdateTime(Date.from(Instant.now()));

        // 获取订单数据, 就算删除也不管. 先更新订单状态
        DiscountOrderExample example = new DiscountOrderExample();
        example.createCriteria()
                .andOrderNoEqualTo(order.getOrderNo())
                // 为了处理临界值状态,被取消的订单照样能被修改为支付完成
                .andOrderStatusIn(Lists.newArrayList(DiscountOrderStatus.CREATE.real(), DiscountOrderStatus.CANCEL.real()));

        dao.updateByExampleSelective(record,
                example,
                Column.paymentChannel,
                Column.paymentNo,
                Column.paymentTime,
                Column.paymentRMBAmount,
                Column.orderStatus,
                Column.updateUser,
                Column.updateTime);
        DiscountOrder discountOrder = getByOrderNo(order.getOrderNo());
        DiscountOrderOutinfo outinfo = outinfoManager.getByOrderId(discountOrder.getOrderId());
        //订单包含渠道信息，需要做订单推送
        if(Check.notNull(outinfo)) {
        	DiscountProductWithBLOBs product = discountProductManager.getById(discountOrder.getProductId());
        	if(DiscountOrderChannel.DAZHONG.equal(outinfo.getChannel())) {
        		daZhongOrderPushExternalService.sendOrder(discountOrder, product, outinfo);
        	}
        }
    }

    /**
     * 退款通知
     */
    void refundedNotify(PaymentOrder order, String updateUser) {
        // TODO 没有退款流程
    }

    /**
     * 修改为处理中状态
     */
    public boolean updateToProcessingStatus(DiscountOrder order, String updateUser) {
        order.setOrderStatus(DiscountOrderStatus.PROCESS.real());
        order.setProcessStatus(DiscountOrderProcessStatus.PROCESSING.real());
        order.setUpdateUser(updateUser);
        order.setUpdateTime(Date.from(Instant.now()));

        DiscountOrderExample example = new DiscountOrderExample();
        example.createCriteria()
                .andOrderStatusEqualTo(DiscountOrderStatus.PAID.real())
                .andProcessStatusEqualTo(DiscountOrderProcessStatus.UNKNOWN.real())
                .andDeletedEqualTo(NOT_DELETED);

        int row = dao.updateByExampleSelective(order,
                example,
                Column.orderStatus,
                Column.processStatus,
                Column.updateUser,
                Column.updateTime);

        return row == 1;
    }

    /**
     * 修改为处理成功状态
     */
    public boolean updateToProcessSucceedStatus(DiscountOrder order, String updateUser) {
        // 详情列表
        List<DiscountOrderDetail> detailList = discountOrderDetailManager.queryByOrderId(order.getOrderId());
        // 计算最终的过期时间
        Date finalExpiretime = null;
        for (DiscountOrderDetail detail : detailList) {
            if (Check.notNull(detail.getExpiretime())) {
                if (finalExpiretime == null || Check.isGreatThan(detail.getExpiretime(), finalExpiretime)){
                    finalExpiretime = detail.getExpiretime();
                }
            }
        }

        order.setFinalExpiretime(finalExpiretime);
        order.setProcessStatus(DiscountOrderProcessStatus.PROCESS_SUCCEED.real());
        order.setUpdateUser(updateUser);
        order.setUpdateTime(Date.from(Instant.now()));

        DiscountOrderExample example = new DiscountOrderExample();
        example.createCriteria()
                .andOrderStatusEqualTo(DiscountOrderStatus.PROCESS.real())
                .andProcessStatusEqualTo(DiscountOrderProcessStatus.PROCESSING.real());

        int row = dao.updateByExampleSelective(order,
                example,
                Column.finalExpiretime,
                Column.processStatus,
                Column.updateUser,
                Column.updateTime);

        return row == 1;
    }

    /**
     * 修改为处理失败状态
     */
    public void updateToProcessFailedStatus(DiscountOrder order, String failedReason, String updateUser) {
        order.setProcessStatus(DiscountOrderProcessStatus.PROCESS_FAILED.real());
        order.setProcessFailedReason(failedReason);
        order.setUpdateUser(updateUser);
        order.setUpdateTime(Date.from(Instant.now()));
        if(DiscountProductServiceType.YOU_WORLD.equal(order.getServiceType())) {
        	order.setOrderStatus(DiscountOrderStatus.REFUND.real());
        	order.setRefundStatus(DiscountOrderRefundStatus.REFUND_SUCCEED.real());
        }
        DiscountOrderExample example = new DiscountOrderExample();
        example.createCriteria()
                .andOrderStatusEqualTo(DiscountOrderStatus.PROCESS.real())
                .andProcessStatusEqualTo(DiscountOrderProcessStatus.PROCESSING.real());

        int row = dao.updateByExampleSelective(order,
                example,
                Column.orderStatus,
                Column.refundStatus,
                Column.processFailedReason,
                Column.processStatus,
                Column.updateUser,
                Column.updateTime);
        BizAssert.isTrue(row==1,ResultCode.BIZ.build(1), "修改处理结果失败");
        if(DiscountProductServiceType.YOU_WORLD.equal(order.getServiceType())) {
	        //发起自动退款
	        BizAssert.isTrue(nihaoPayService.refundApply(order.getOrderNo(),order.getTotalPrice(), updateUser),ResultCode.BIZ.build(2), "自动退款失败");
        }
    }

    /**
     * 取消订单
     */
    @Transactional
    public boolean cancel(Integer userId, Integer orderId, String updateUser) {
    	DiscountOrder order = getById(userId,orderId);
        order.setOrderStatus(DiscountOrderStatus.CANCEL.real());
        order.setCancelStatus(DiscountOrderCancelStatus.CANCEL.real());
        order.setUpdateUser(updateUser);
        order.setUpdateTime(Date.from(Instant.now()));

        DiscountOrderExample example = new DiscountOrderExample();
        example.createCriteria()
                .andOrderIdEqualTo(orderId)
                .andUserIdEqualTo(userId)
                .andOrderStatusEqualTo(DiscountOrderStatus.CREATE.real())
                .andDeletedEqualTo(NOT_DELETED);

        int row = dao.updateByExampleSelective(order,
                example,
                Column.orderStatus,
                Column.cancelStatus,
                Column.updateUser,
                Column.updateTime);

        BizAssert.isTrue(row == 1, ResultCode.BIZ.build(1), "取消订单失败");

        // 解冻
        unfreeze(getById(userId, orderId), updateUser);

        return row == 1;
    }

    /**
     * 查询超时支付的订单
     *
     * @param timeoutMinutes
     * @param size
     *
     * @return
     */
    public List<DiscountOrder> queryOverduePay(Integer timeoutMinutes, Integer size) {
        // 超时时间
        Date timeout = Date.from(Instant.now().minus(timeoutMinutes, ChronoUnit.MINUTES));

        DiscountOrderExample example = new DiscountOrderExample();
        example.createCriteria()
                .andOrderStatusEqualTo(DiscountOrderStatus.CREATE.real())
                .andCancelStatusEqualTo(DiscountOrderCancelStatus.UNKNOWN.real())
                .andCreateTimeLessThanOrEqualTo(timeout)
                .andDeletedEqualTo(NOT_DELETED);

        example.setRows(size);
        return dao.selectByExample(example);
    }

    /**
     * 自动取消
     */
    @Transactional
    public boolean autoCancel(DiscountOrder order, String updateUser) {
        order.setOrderStatus(DiscountOrderStatus.CANCEL.real());
        order.setCancelStatus(DiscountOrderCancelStatus.AUTO_CANCEL.real());
        order.setUpdateUser(updateUser);
        order.setUpdateTime(Date.from(Instant.now()));

        DiscountOrderExample example = new DiscountOrderExample();
        example.createCriteria()
                .andOrderIdEqualTo(order.getOrderId())
                .andOrderStatusEqualTo(DiscountOrderStatus.CREATE.real())
                .andCancelStatusEqualTo(DiscountOrderCancelStatus.UNKNOWN.real())
                .andDeletedEqualTo(NOT_DELETED);

        int row = dao.updateByExampleSelective(order,
                example,
                Column.orderStatus,
                Column.cancelStatus,
                Column.updateUser,
                Column.updateTime);

        // 解冻
        if (row == 1) {
            unfreeze(order, updateUser);
        }

        return row == 1;
    }

    /**
     * 删除订单
     */
    public boolean delete(Integer userId, Integer orderId, String updateUser) {
        DiscountOrder order = new DiscountOrder();
        order.setDeleted(IS_DELETED);
        order.setUpdateUser(updateUser);
        order.setUpdateTime(Date.from(Instant.now()));

        DiscountOrderExample example = new DiscountOrderExample();
        example.createCriteria()
                .andOrderIdEqualTo(orderId)
                .andUserIdEqualTo(userId)
                .andOrderStatusEqualTo(DiscountOrderStatus.CANCEL.real())
                .andDeletedEqualTo(NOT_DELETED);

        int row = dao.updateByExampleSelective(order,
                example,
                Column.orderStatus,
                Column.cancelStatus,
                Column.updateUser,
                Column.updateTime);

        BizAssert.isTrue(row == 1, ResultCode.BIZ.build(1), "删除订单失败");

        return row == 1;
    }

    /**
     * 确认完成
     */
    public boolean confirmComplete(Integer userId, Integer orderId, String updateUser) {
    	DiscountOrder order = getById(userId,orderId);
        order.setOrderStatus(DiscountOrderStatus.COMPLETE.real());
        order.setCompleteStatus(DiscountOrderCompleteStatus.COMPLETED.real());
        order.setUpdateUser(updateUser);
        order.setUpdateTime(Date.from(Instant.now()));

        DiscountOrderExample example = new DiscountOrderExample();
        example.createCriteria()
                .andOrderIdEqualTo(orderId)
                .andUserIdEqualTo(userId)
                .andOrderStatusEqualTo(DiscountOrderStatus.COMPLETE.real())
                .andProcessStatusEqualTo(DiscountOrderProcessStatus.PROCESS_SUCCEED.real())
                .andCompleteStatusEqualTo(DiscountOrderCompleteStatus.PART_COMPLETED.real())
                .andDeletedEqualTo(NOT_DELETED);

        int row = dao.updateByExampleSelective(order,
                example,
                Column.orderStatus,
                Column.completeStatus,
                Column.updateUser,
                Column.updateTime);

        BizAssert.isTrue(row == 1, ResultCode.BIZ.build(1), "确认订单失败");

        // 把卡券标记使用
        cardVoucherPackageManager.updateStatusToUsed(orderId, updateUser);

        return row == 1;
    }
    
    /**
     * 部分确认完成
     * @param userId
     * @param orderId
     * @param updateUser
     * @return
     * @throws BizException
     */
    public boolean confirmPartCompleteOrder(Integer userId, Integer orderId, String updateUser) throws BizException {
    	DiscountOrder order = getById(userId,orderId);
        order.setOrderStatus(DiscountOrderStatus.COMPLETE.real());
        order.setCompleteStatus(DiscountOrderCompleteStatus.PART_COMPLETED.real());
        order.setUpdateUser(updateUser);
        order.setUpdateTime(Date.from(Instant.now()));

        DiscountOrderExample example = new DiscountOrderExample();
        example.createCriteria()
                .andOrderIdEqualTo(orderId)
                .andUserIdEqualTo(userId)
                .andOrderStatusEqualTo(DiscountOrderStatus.PROCESS.real())
                .andProcessStatusEqualTo(DiscountOrderProcessStatus.PROCESS_SUCCEED.real())
                .andCompleteStatusEqualTo(DiscountOrderCompleteStatus.UNKNOWN.real())
                .andDeletedEqualTo(NOT_DELETED);

        int row = dao.updateByExampleSelective(order,
                example,
                Column.orderStatus,
                Column.completeStatus,
                Column.updateUser,
                Column.updateTime);

        BizAssert.isTrue(row == 1, ResultCode.BIZ.build(1), "确认订单失败");

        return row == 1;
	}

    /**
     * 发起退款
     *
     * @param orderId
     * @param updateUser
     */
    public Boolean refund(DiscountOrder order,Boolean cardUsed,String reasonType,String reasonComments,Boolean useBindPhone,String contactPhone, String updateUser) {
    	if(DiscountProductServiceType.YOU_WORLD.equal(order.getServiceType())) {
    		String phone = null;
    		if(!useBindPhone) {
    			BizAssert.isTrue(Check.notNull(contactPhone), ResultCode.VERIFY.build(10), "联系电话不能为空");
    			phone = contactPhone;
    		}else {
    			phone = order.getMobileNumber();
    		}
    		List<DiscountOrderDetail> orderDetailList = discountOrderDetailManager.queryByOrderId(order.getOrderId());
    		if(Check.notNullOrEmpty(orderDetailList)) {
    			Boolean flag = youWorldService.sendRefundRequest(orderDetailList.get(0).getTransNo(), cardUsed, reasonType, reasonComments, phone);
    			//发起退款成功
    			if(flag) {
    				//创建退款单
    				DiscountOrderRefund discountOrderRefund = new DiscountOrderRefund();
            		discountOrderRefund.setCardUsed(cardUsed);
            		discountOrderRefund.setContactPhone(phone);
            		discountOrderRefund.setOrderId(order.getOrderId());
            		discountOrderRefund.setReasonType(reasonType);
            		discountOrderRefund.setReasonComments(reasonComments);
            		discountOrderRefund.setRefundStatus("pending");
            		discountOrderRefund.setApplyTime(Date.from(Instant.now()));
            		discountOrderRefundManager.create(discountOrderRefund, updateUser);
            		//更新订单状态
            		order.setOrderStatus(DiscountOrderStatus.REFUND.real());
            		order.setRefundStatus(DiscountOrderRefundStatus.APPLY_REFUND.real());
            		update(order,updateUser);
    			}
    			return flag;
    		}
    	}
    	return false;
    }
    
    /**
     * 取消退款
     * @param order
     * @param updateUser
     * @throws BizException
     */
    public Boolean cancelRefund(DiscountOrder order, String updateUser){
    	if(DiscountProductServiceType.YOU_WORLD.equal(order.getServiceType())) {
    		List<DiscountOrderDetail> orderDetailList = discountOrderDetailManager.queryByOrderId(order.getOrderId());
    		if(Check.notNullOrEmpty(orderDetailList)) {
    			Boolean flag = youWorldService.cancelRefundRequest(orderDetailList.get(0).getTransNo());
    			if(flag) {
    				discountOrderRefundManager.updateToCancel(order.getOrderId(), updateUser);
    				//更新订单状态
            		order.setOrderStatus(DiscountOrderStatus.PROCESS.real());
            		order.setRefundStatus(DiscountOrderRefundStatus.REFUND_CANCEL.real());
            		update(order,updateUser);
    			}
    			return flag;
    		}
    	}
    	return false;
	}

    public void update(DiscountOrder order, String updateUser) {
    	order.setUpdateUser(updateUser);
    	order.setUpdateTime(Date.from(Instant.now()));
    	dao.updateByPrimaryKey(order);
    }
    
    /**
     * 查询过期状态的订单
     * @param now
     * @param size
     * @return
     */
    public List<DiscountOrder> queryExpireOrder(Date now,int size){
    	DiscountOrderExample example = new DiscountOrderExample();
    	Criteria criteria = example.createCriteria();
    	criteria.andShelfLifeLessThanOrEqualTo(now)
    	.andOrderStatusEqualTo(DiscountOrderStatus.PROCESS.real())
        .andProcessStatusEqualTo(DiscountOrderProcessStatus.PROCESS_SUCCEED.real())
        .andCompleteStatusEqualTo(DiscountOrderCompleteStatus.UNKNOWN.real())
        .andDeletedEqualTo(NOT_DELETED);
    	example.orderBy(Column.shelfLife.asc());
    	example.limit(size);
    	return dao.selectByExample(example);
    }
    
    /**
     * 修改为过期状态
     *
     * @param order
     * @param updateUser
     *
     * @return
     */
    public boolean updateToExpiredStatus(DiscountOrder order, String updateUser) {
        order.setOrderStatus(DiscountOrderStatus.EXPIRED.real());
        order.setUpdateUser(updateUser);
        order.setUpdateTime(Date.from(Instant.now()));


        int row = dao.updateByPrimaryKeySelective(order,
                Column.orderStatus,
                Column.updateUser,
                Column.updateTime);

        return row == 1;
    }

    /**
     * 查询支付完成状态,未处理的订单
     *
     * @param size
     *
     * @return
     */
    public List<DiscountOrder> queryPaidAndUnknownProcessStatus(Integer size) {
        DiscountOrderExample example = new DiscountOrderExample();
        example.createCriteria()
                .andOrderStatusEqualTo(DiscountOrderStatus.PAID.real())
                .andProcessStatusEqualTo(DiscountOrderProcessStatus.UNKNOWN.real())
                .andDeletedEqualTo(NOT_DELETED);

        return dao.selectByExample(example);
    }

    /**
     * 根据订单号查询订单
     *
     * @param orderNo
     *
     * @return
     */
    public DiscountOrder getByOrderNo(String orderNo) {
        DiscountOrderExample example = new DiscountOrderExample();
        example.createCriteria()
                .andOrderNoEqualTo(orderNo)
                .andDeletedEqualTo(NOT_DELETED);
        return dao.selectOneByExample(example);
    }

    /**
     * 用户根据订单Id查询订单
     *
     * @param userId
     * @param orderId
     *
     * @return
     */
    public DiscountOrder getById(Integer userId, Integer orderId) {
        DiscountOrderExample example = new DiscountOrderExample();
        example.createCriteria()
                .andOrderIdEqualTo(orderId)
                .andUserIdEqualTo(userId)
                .andDeletedEqualTo(NOT_DELETED);
        //更新由我付退款单状态
        youWorldService.refreshRefundStatus(dao.selectOneByExample(example));
        return dao.selectOneByExample(example);
    }

    /**
     * 根据ID获取订单
     *
     * @param orderId
     *
     * @return
     */
    public DiscountOrder getById(Integer orderId) {
        DiscountOrderExample example = new DiscountOrderExample();
        example.createCriteria()
                .andOrderIdEqualTo(orderId)
                .andDeletedEqualTo(NOT_DELETED);
        return dao.selectOneByExample(example);
    }

    /**
     * 用户查询订单列表
     *
     * @param userId
     * @param query
     * @param sorts
     * @param page
     *
     * @return
     */
    public Pagination<DiscountOrder> queryByUserId(Integer userId, QueryUserDiscountOrderDTO query, Sorting[] sorts, Page page) {
        DiscountOrderExample example = new DiscountOrderExample();
        DiscountOrderExample.Criteria criteria = example.createCriteria();

        criteria.andUserIdEqualTo(userId)
                .andDeletedEqualTo(NOT_DELETED);

        if (Check.notNullOrTrimEmpty(query.getOrderNo())) {
            criteria.andOrderNoEqualTo(query.getOrderNo());
        }
        if (Check.notNull(query.getRegionType())) {
            criteria.andRegionTypeEqualTo(query.getRegionType());
        }
        if (Check.notNull(query.getBrandId())) {
            criteria.andBrandIdEqualTo(query.getBrandId());
        }
        if (Check.notNull(query.getProductId())) {
            criteria.andProductIdEqualTo(query.getProductId());
        }
        if (Check.notNull(query.getDiscountMode())) {
            criteria.andDiscountModeEqualTo(query.getDiscountMode());
        }
        if (Check.notNullOrEmpty(query.getOrderStatus())) {
            if (query.getOrderStatus().length == 1) {
                criteria.andOrderStatusEqualTo(query.getOrderStatus()[0]);
            } else {
                criteria.andOrderStatusIn(Lists.newArrayList(query.getOrderStatus()));
            }
        }
        if (Check.notNullOrEmpty(query.getNotOrderStatus())) {
            if (query.getNotOrderStatus().length == 1) {
                criteria.andOrderStatusNotEqualTo(query.getNotOrderStatus()[0]);
            } else {
                criteria.andOrderStatusNotIn(Lists.newArrayList(query.getNotOrderStatus()));
            }
        }
        if (Check.notNull(query.getCompleteStatus())) {
            criteria.andCompleteStatusEqualTo(query.getCompleteStatus());
        }
        
        example.orderBy(Sortings.builder(sorts).verify(Column::valueOf).toSql());
        example.setOffset(page.getFirstIndex());
        example.setRows(page.getPageSize());
        //更新由我付订单退款状态
        youWorldService.refreshRefundStatusList(dao.selectByExample(example));
        return Pagination.create(page, dao.countByExample(example), () -> dao.selectByExample(example));
    }

    public Pagination<DiscountOrder> query(QueryDiscountOrderDTO query, Sorting[] sorts, Page page) {
        DiscountOrderExample example = new DiscountOrderExample();
        DiscountOrderExample.Criteria criteria = example.createCriteria();

        criteria.andDeletedEqualTo(NOT_DELETED);

        if (Check.notNull(query.getUserId())) {
            criteria.andUserIdEqualTo(query.getUserId());
        }
        if (Check.notNullOrTrimEmpty(query.getOrderNo())) {
            criteria.andOrderNoEqualTo(query.getOrderNo());
        }
        if (Check.notNull(query.getRegionType())) {
            criteria.andRegionTypeEqualTo(query.getRegionType());
        }
        if (Check.notNull(query.getBrandId())) {
            criteria.andBrandIdEqualTo(query.getBrandId());
        }
        if (Check.notNull(query.getProductId())) {
            criteria.andProductIdEqualTo(query.getProductId());
        }
        if (Check.notNull(query.getDiscountMode())) {
            criteria.andDiscountModeEqualTo(query.getDiscountMode());
        }
        if (Check.notNullOrEmpty(query.getOrderStatus())) {
            if (query.getOrderStatus().length == 1) {
                criteria.andOrderStatusEqualTo(query.getOrderStatus()[0]);
            } else {
                criteria.andOrderStatusIn(Lists.newArrayList(query.getOrderStatus()));
            }
        }
        if (Check.notNullOrEmpty(query.getNotOrderStatus())) {
            if (query.getNotOrderStatus().length == 1) {
                criteria.andOrderStatusNotEqualTo(query.getNotOrderStatus()[0]);
            } else {
                criteria.andOrderStatusNotIn(Lists.newArrayList(query.getNotOrderStatus()));
            }
        }
        if (Check.notNull(query.getCompleteStatus())) {
            criteria.andCompleteStatusEqualTo(query.getCompleteStatus());
        }

        example.orderBy(Sortings.builder(sorts).verify(Column::valueOf).toSql());
        example.setOffset(page.getFirstIndex());
        example.setRows(page.getPageSize());

        return Pagination.create(page, dao.countByExample(example), () -> dao.selectByExample(example));
    }
}